﻿using System;
using System.Drawing;

namespace Forms {
	internal class ColorHSL {
		private byte a;
		private float h;
		private float s;
		private float l;

		public byte A { get => a; set => a = value; }
		public float H { get => h; set {
				while (value >= 360) {
                    value -= 360;
                }
                while (value <0 ) {
                    value += 360;
                }
                h = value;
            }
        }
        public float S {
			get => s; set {
				if (value > 100) { value = 100; }
				if (value < 0) { value = 0; }
				s = value;
			}
		}
        public float L {
			get => l; set {
                if (value > 100) { value = 100; }
                if (value < 0) { value = 0; }
                l = value;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="h">色相 [0,360)</param>
		/// <param name="s">饱和度 [0,100]</param>
		/// <param name="l">亮度 [0,100]</param>
		/// <param name="a">不透明度，和Color一致</param>
		internal ColorHSL(float h,float s,float l, byte a) {
            H = h;
			S = s;
			L = l;
			A = a;
		}
		/// <summary>  
		/// RGB转换HSL  
		/// </summary>  
		/// <param name="c"></param>  
		/// <returns></returns>  
		internal ColorHSL(Color c) {
			A = c.A;
			float min, max;
			min = Math.Min(Math.Min(c.R, c.G), c.B);
			max = Math.Max(Math.Max(c.R, c.G), c.B);
			if (max == min) {
				H = 0; 
				S = 0;
				L = 100f * (max + min) / (2f * 255f);
			} else {
				L = 100f * (max + min) / (2f * 255f);
				if (max == c.R) {
					H = 60f * (c.G - c.B) / (max - min) + 0;
				} else if (max == c.G) {
					H = 60f * (c.B - c.R) / (max - min) + 120;
				} else if (max == c.B) {
					H = 60f * (c.R - c.G) / (max - min) + 240;
				} else {
					throw new Exception("不可能发生max不等于RGB三个值");
				}
				if (L <= 50f) {
					S = (max - min) * 100f / (max + min);
				} else {
					S = (max - min) * 100f / (2 * 255 - (max + min));
				}
			}
		}

		/// <summary>  
		/// HSL转换RGB  
		/// </summary>  
		/// <param name="hsl"></param>  
		/// <returns></returns>  
		internal Color HslToRgb() {
			float s = this.S / 100;
			float l = this.L / 100;
			float h = this.H / 360 ;
			float p, q;
			if (s == 0) {
				return Color.FromArgb(this.A, 
					(int)(l * 255f + 0.5f), 
					(int)(l * 255f + 0.5f),
					(int)(l * 255f + 0.5f));
			} else {
				if (l < 0.5) {
					q = l  + (s * l);
				} else { 
					q = l + s - (s * l);
				}
				p = 2f * l - q;
				float Hue2RGB(float vH) {
					if (vH < 0) vH += 1;
					if (vH >= 1) vH -= 1;
					if (vH < 1 / 6f) {
						return p + (q - p) * 6f * vH;
					} else if (vH < 1 / 2f) {
						return q;
					} else if (vH < 2 / 3f) {
						return p + (q - p) * ((2f / 3f) - vH) * 6f;
					} else {
						return p;
					}
				}
				return Color.FromArgb(this.A, 
					(int)(0.5f + 255f * Hue2RGB(h + (1f / 3f))), 
					(int)(0.5f + 255f * Hue2RGB(h)),
					(int)(0.5f + 255f * Hue2RGB(h - (1f / 3f))) );

			}
		}

		public static implicit operator Color(ColorHSL c) {
            return c.HslToRgb();
        }



    }
}
